package com.zrrd.jt_admin.common.utils;

import com.zrrd.jt_admin.common.exception.TokenException;
import io.jsonwebtoken.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.DigestUtils;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.*;

/**
 * @author ZhangYK
 * @version 8.0
 * @title JwtUtils
 * @description
 * @create 2024/6/28 14:22
 */
public class JwtUtils {
    // TOKEN的有效期一天（S）
    private static final int TOKEN_TIME_OUT = 3_600;
    // 加密KEY
    // 字符串“zhangyk”通过MD5加密，加密后内容进行Base64加密生成43位字符串。作为通用加密KEY
    private static final String TOKEN_ENCRY_KEY = "MzE1NDdjMjJjOTNkNDRjZjRlODg3ZGRhNjIwMGFmNWU";
    // 最小刷新间隔(S)
    private static final int REFRESH_TIME = 300;
    private static final Logger log = LoggerFactory.getLogger(JwtUtils.class);

    // 生产ID
    public static String getToken(Long id){
        Map<String, Object> claimMaps = new HashMap<>();
        claimMaps.put("id",id);
        long currentTime = System.currentTimeMillis();
        return Jwts.builder()
                .setId(UUID.randomUUID().toString())
                .setIssuedAt(new Date(currentTime))  //签发时间
                .setSubject("system")  //说明
                .setIssuer("wanjl") //签发者信息
                .setAudience("app")  //接收用户
                .compressWith(CompressionCodecs.GZIP)  //数据压缩方式
                .signWith(SignatureAlgorithm.HS512, generalKey()) //加密方式
                .setExpiration(new Date(currentTime + TOKEN_TIME_OUT * 1000))  //过期时间戳
                .addClaims(claimMaps) //cla信息
                .compact();
    }

    /**
     * 获取token中的claims信息
     *
     * @param token
     * @return
     */
    private static Jws<Claims> getJws(String token) {
        return Jwts.parser()
                .setSigningKey(generalKey())
                .parseClaimsJws(token);
    }

    /**
     * 获取payload body信息
     *
     * @param token
     * @return
     */
    public static Claims getClaimsBody(String token) {
        try {
            return getJws(token).getBody();
        }catch (ExpiredJwtException e){
            return null;
        }
    }

    /**
     * 获取hearder body信息
     *
     * @param token
     * @return
     */
    public static JwsHeader getHeaderBody(String token) {
        return getJws(token).getHeader();
    }

    /**
     * 是否过期
     *
     * @param claims
     * @return -1：有效，0：有效，1：过期，2：过期
     */
    public static int verifyToken(Claims claims) {
        if(claims==null){
            return 1;
        }
        try {
            claims.getExpiration()
                    .before(new Date());
            // 需要自动刷新TOKEN
            if((claims.getExpiration().getTime()-System.currentTimeMillis())>REFRESH_TIME*1000){
                return -1;
            }else {
                return 0;
            }
        } catch (ExpiredJwtException ex) {
            return 1;
        }catch (Exception e){
            return 2;
        }
    }

    /**
     * 由字符串生成加密key
     *
     * @return
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.getEncoder().encode(TOKEN_ENCRY_KEY.getBytes());
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }

    /**
     * 解析令牌
     *
     * @param token
     * @return
     */
    public static Map<String, Object> analysisToken(String token) {
        try{
            //判空
            if(token==null){
                throw new TokenException("令牌为空");
            }
            //解析JWT，获取jwt中的载荷数据
            Claims claimsBody = getClaimsBody(token);
            log.info("ClaimsBody:"+claimsBody);
            if(claimsBody==null){
                //throw new TokenException("载荷数据为空，令牌已过期");
                log.error("载荷数据为空，令牌已过期");
                return null;
            }
            return claimsBody;
        }catch (TokenException e){
            e.printStackTrace();
        }catch (ExpiredJwtException e){
            throw new RuntimeException("令牌已过期");
        }catch (Exception e){
            throw new RuntimeException("令牌解析异常");
        }
        return null;
    }

    public static void main(String[] args) {
       /* Map map = new HashMap();
        map.put("id","11");*/
//        System.out.println(JwtUtils.getToken(3l));
//        Jws<Claims> jws = JwtUtils.getJws("填写由上一行生成的token");
//        Claims claims = jws.getBody();
//        System.out.println(claims.get("id"));


        String pwd = DigestUtils.md5DigestAsHex(("admin"+JwtUtils.generalKey()).getBytes());
        System.out.println(pwd);
    }
}
